/*****************************************************************************/
/* This is the program skeleton for homework 2 in CS 184 by Ravi Ramamoorthi */
/* Extends HW 1 to deal with shading, more transforms and multiple objects   */
/*****************************************************************************/

// This is the basic include file for the global variables in the program.  
// Since all files need access to it, we define EXTERN as either blank or 
// extern, depending on if included in the main program or not.  
#pragma once

#include <glm\glm.hpp>

#ifdef MAINPROGRAM 
#define EXTERN
#else 
#define EXTERN extern
#endif 

EXTERN int amount; // The amount of rotation for each arrow press
EXTERN glm::vec3 eye; // The (regularly updated) vector coordinates of the eye 
EXTERN glm::vec3 up;  // The (regularly updated) vector coordinates of the up 

#ifdef MAINPROGRAM 
vec3 eyeinit(0.0,0.0,5.0) ; // Initial eye position, also for resets
vec3 upinit(0.0,1.0,0.0) ; // Initial up position, also for resets
vec3 center(0.0,0.0,0.0) ; // Center look at point 
int w = 600, h = 400 ; // width and height 
float fovy = 90.0 ; // For field of view
#else 
EXTERN glm::vec3 eyeinit ; 
EXTERN glm::vec3 upinit ; 
EXTERN glm::vec3 center ; 
EXTERN int w, h ; 
EXTERN float fovy ; 
#endif 

EXTERN bool useGlu; // Toggle use of "official" opengl/glm transform vs user 
EXTERN bool useTextures;
EXTERN bool useCel;
EXTERN bool useBW;
EXTERN bool useBump;
EXTERN GLuint vertexshader, fragmentshader, shaderprogram; // shaders
static enum {view, translate, scale, firstp} transop ; // which operation to transform 
EXTERN float sx, sy ; // the scale in x and y 
EXTERN float tx, ty ; // the translation in x and y
EXTERN int animate; //varies between 0 and 10000 with time. Used for animation
EXTERN int doorstate; //holds the state of the door
EXTERN int mouseX, mouseY ; //values holding the previous values of X and Y for mouse.
EXTERN bool mouseInit;

// Lighting parameter array, similar to that in the fragment shader
const int numLights = 10 ; 
EXTERN GLfloat lightposn [4*numLights] ; // Light Positions
EXTERN GLfloat lightcolor[4*numLights] ; // Light Colors
EXTERN GLfloat lightransf[4*numLights] ; // Lights transformed by modelview
EXTERN int numused ;                     // How many lights are used 

// Materials (read from file) 
// With multiple objects, these are colors for each.
EXTERN GLfloat ambient[4] ; 
EXTERN GLfloat diffuse[4] ; 
EXTERN GLfloat specular[4] ; 
EXTERN GLfloat emission[4] ; 
EXTERN GLfloat shininess ; 

// For multiple objects, read from a file.  
/*
const int maxobjects = 50 ; 
EXTERN int numobjects ; 
EXTERN struct object {
  //shape type ; 
	int type;
  GLfloat size ;
  GLfloat ambient[4] ; 
  GLfloat diffuse[4] ; 
  GLfloat specular[4] ;
  GLfloat emission[4] ; 
  GLfloat shininess ;
  mat4 transform ; 
} objects[maxobjects] ;
*/


// Variables to set uniform params for lighting fragment shader 
EXTERN GLuint lightcol ; 
EXTERN GLuint lightpos ; 
EXTERN GLuint numusedcol ; 
EXTERN GLuint enablelighting ; 
EXTERN GLuint ambientcol ; 
EXTERN GLuint diffusecol ; 
EXTERN GLuint specularcol ; 
EXTERN GLuint emissioncol ; 
EXTERN GLuint shininesscol ; 
EXTERN GLuint texture_location;
EXTERN GLuint enable_textures;
EXTERN GLuint textured_object;
EXTERN GLuint enable_cel_shading;
EXTERN GLuint enable_bw;
EXTERN GLuint bumpmap_location;
EXTERN GLuint enable_bump;
EXTERN GLuint bumpmap_object;


const int numstars =80;
EXTERN glm::vec3 stars[numstars];
const GLfloat starambient[4] = {1,1,1,1};
const GLfloat stardiffuse[4] = {.5, .5, .5, 1};
const GLfloat starspecular[4] = {.05,.05,.05, 1};
const GLfloat staremission[4] = {0, 0, 0, 0};
const GLfloat starshininess = 10;


//HW0 code for instantiating objects
const int numobjects = 2 ; 
const int numperobj  = 3 ;
const int ncolors = 1 ; 
EXTERN GLenum PrimType[numobjects] ;
EXTERN GLsizei NumElems[numobjects] ; 
EXTERN GLuint buffers[numperobj*numobjects+ncolors+1] ;

#define BUFFER_OFFSET(bytes) ((GLubyte *) NULL + (bytes))
#define NumberOf(array) (sizeof(array)/sizeof(array[0])) 

EXTERN enum {Vertices, Colors, Elements} ; // For arrays for object 
EXTERN enum {FLOOR, CUBE} ; // For objects, for the floor

const GLfloat wd = 0.05 ; 
const GLfloat ht = 0.05 ; 
const GLfloat _cubecol[1][3] = { 
	{1.0, 1.0, 0.0}};//, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}, {1.0, 1.0, 0.0} } ; 
const GLfloat cubeverts[8][3] = {
		{-wd, -wd, 0.0}, {-wd, wd, 0.0}, {wd, wd, 0.0}, {wd, -wd, 0.0},
		{-wd, -wd, ht}, {wd, -wd, ht}, {wd, wd, ht}, {-wd, wd, ht}
	} ; 
EXTERN GLfloat cubecol[8][3] ;
const GLubyte cubeinds[6][4] = { 
	{0, 1, 2, 3}, // BOTTOM 
	{4, 5, 6, 7}, // TOP 
	{0, 4, 7, 1}, // LEFT 
	{0, 3, 5, 4}, // FRONT
	{3, 2, 6, 5}, // RIGHT 
	{1, 7, 6, 2}  // BACK
} ; 

void initobjectnocol(GLuint object, GLfloat * vert, GLint sizevert, GLubyte * inds, GLint sizeind, GLenum type);

void drawobject(GLuint object);

void initcolorscube (void);

void drawcolor(GLuint object, GLuint color);